
#include <BStyle>
#include <BPainter>
#include <BRender>
#include <BViewer>
#include <BScene>
#include <BCone>
#include <BCube>
#include <BImage>
#include <BMaterial>
#include <BReadWrite>

#include <BFixedRestraint>
#include "StripeSliderHandler.h"

StripeSliderHandler::StripeSliderHandler()
{
	_fixedRestraint = 0;
	_stripeRestraint = 0;

	_layout = new BHBoxLayout();
	{
		_valueSpinBox = new BRealSpinBox();
		_valueSlider = new BRealSlider();
		_layout->addWidget(_valueSpinBox, 0);
		_layout->addWidget(_valueSlider);
		_layout->setMinWidth(800);
	}

	_group = new BGroup();

	_nodeA = new BBody("nodeA");
	{
		_nodeA->setMass(0);
		_nodeA->setGravity(0, 0, -10);
		_nodeA->move(0, 0, 0.5);

		BCube* cube = new BCube(1, 12);
		cube->setColor(100, 200, 10);
		_nodeA->insertShape(cube);

		_lineStripe = new BLineStripe();
		{
			BVectorArray* vertices = new BVectorArray();
			vertices->append(BVector(0, 0, 1));
			vertices->append(BVector(1, 0, 1));
			vertices->append(BVector(1.5, 1, 1));
			vertices->append(BVector(1, 2, 1));
			vertices->append(BVector(0, 3, 1));
			vertices->append(BVector(-1, 3, 1));
			vertices->append(BVector(-2, 0, 1));
			vertices->append(BVector(-1, -1, 1));
			_lineStripe->setVertices(vertices);
			_lineStripe->setRadius(0.1);
			_lineStripe->setCloseLoop(true);
		}
		_nodeA->insertShape(_lineStripe);

		_group->insert(_nodeA);
	}

	_nodeB = new BBody("nodeB");
	{
		_nodeB->setMass(1);
		_nodeB->setGravity(0, 0, -10);

		BCone* cone = new BCone(0.1, 0.2, 24, 10);
		cone->setColor(200, 100, 0);
		cone->setPolySmooth(true);
		_nodeB->insertShape(cone);
		_group->insert(_nodeB);
	}

	_nodeC = new BBody("nodeC");
	{
		_nodeC->setMass(1);
		_nodeC->setGravity(0, 0, -10);

		BCube* cube = new BCube(0.1, 0.1, 1, 12);
		cube->setColor(100, 200, 255);
		_nodeC->insertShape(cube);
		_group->insert(_nodeC);
	}

	_stripeRestraint = new BSliderRestraint(_nodeA, _nodeB);
	_stripeRestraint->setStripe(_lineStripe);
	_stripeRestraint->setPivotB(0, 0, -(0.2 / 3));
	_stripeRestraint->setAxisA(BVector(1, 0, 0));
	_stripeRestraint->setAxisB(BVector(1, 0, 0));
	_stripeRestraint->setColliding(true);
	_group->insert(_stripeRestraint);

	_valueSlider->setRange(0, _lineStripe->length());

	connect(_valueSlider, Signal_Sliding, &StripeSliderHandler::slotValueSliderSliding);
	connect(_lineStripe, Signal_Flushed, &StripeSliderHandler::slotLineStripeFlushed);
}
StripeSliderHandler::~StripeSliderHandler()
{

}

void StripeSliderHandler::slotValueSliderSliding(BObject* object, const BValue& value)
{
	BMatrix matrix = _nodeA->matrix() * _lineStripe->matrix();
	_debugPoint = _lineStripe->vertexOf(value);
	_debugDirect = _lineStripe->directOf(value);
	_debugPoint = matrix * _debugPoint;
	_debugDirect = matrix.mult3(_debugDirect);
	_valueSpinBox->setValue(value);
}
void StripeSliderHandler::slotLineStripeFlushed(BObject* object, const BValue& value)
{
	_valueSlider->setRange(0, _lineStripe->length());
}

void StripeSliderHandler::attached(BViewer* viewer)
{
	BScene* dscene = viewer->scene();
	dscene->insert(_group);
	this->emit("show-note", _layout);
	this->emit("edit-shape", _lineStripe);
	this->emit("edit-restraint", _stripeRestraint);
}
void StripeSliderHandler::detached(BViewer* viewer)
{
	BScene* dscene = viewer->scene();
	dscene->remove(_group);
	this->emit("hide-note", _layout);
	this->emit("edit-shape", 0);
	this->emit("edit-restraint", 0);
}

void StripeSliderHandler::paint(BPainter& painter)
{
	BViewer* viewer = this->viewer();

}
void StripeSliderHandler::render(BRender& render)
{
	render.setLighting(false);
	render.setDepthTest(false);
	render.setLineSmooth(true);
	render.setLineWidth(1);

	if (_fixedRestraint)
	{
		const BVector& center = _fixedRestraint->property("center");
		render.setColor(255, 0, 0);
		render.setPointSize(10);
		render.drawVertex(center);

		const BBox& box = _fixedRestraint->property("box");
		render.setColor(0, 255, 255);
		render.drawBox(box);
	}
	if (_stripeRestraint)
	{
		render.setLineStipple(0xf0f0);

		const BMatrix& matrixA = _stripeRestraint->bodyA()->matrix();
		BVector pivotA = matrixA * _stripeRestraint->pivotA();
		BVector axisA = matrixA.mult3(_stripeRestraint->axisA());
		render.setColor(200, 0, 200);
		render.drawLine(pivotA, pivotA + axisA);

		const BMatrix& matrixB = _stripeRestraint->bodyB()->matrix();
		BVector pivotB = matrixB * _stripeRestraint->pivotB();
		BVector axisB = matrixB.mult3(_stripeRestraint->axisB() * 0.5);
		render.setColor(0, 200, 200);
		render.drawLine(pivotB, pivotB + axisB);

		render.setLineStipple(0x0000);

		if (BLineStripe* stripe = _stripeRestraint->stripe())
		{
			render.setPointSize(16);
			render.setColor(255, 0, 0);
			BVector point = stripe->vertexOf(_stripeRestraint->linearPos());
			point *= _nodeA->matrix() * stripe->matrix();
			render.drawVertex(point);
		}
	}

	render.setColor(200, 0, 0);
	render.setPointSize(6);
	render.drawVertex(_debugPoint);

	render.setColor(100, 200, 100);
	render.setLineWidth(2);
	render.drawLine(_debugPoint, _debugPoint + _debugDirect);
}

void StripeSliderHandler::styleEvent(const BEvent& event)
{
	BHandler::styleEvent(event);
	const BStyle* style = event.value();
	BImage* image = style->image("cone-texture");
	if (BShape* shape = _nodeB->shape(0))
	{
		shape->setTexture(image);
	}
}
